/*
 *  Arrow
 *
 *  Created by David Giovannini on 1/5/07.
 *  Copyright 2007 Software by Jove. All rights reserved.
 *
 */
 
#ifndef SBJ_Arrow_MsgProxy_h
#define SBJ_Arrow_MsgProxy_h

#include "SBJ/Arrow/Message.h"
#include "SBJ/Interfaces/IExceptionObserver.h"
#include "SBJ/Memory/NCAllocator.h"

#include <boost/noncopyable.hpp>
#include <boost/logic/tribool.hpp>

namespace SBJ
{

class IExceptionObserver;

namespace Arrow
{

/*
	MsgProxy supplies support for specific message types used by the 
	event service.
	
	Motivation:
	MsgType safety and memory reuse.
*/

class MsgProxy : private boost::noncopyable
{
public:
	virtual ~MsgProxy( void ) {}

	virtual size_t getMsgSize( void ) const = 0;

	virtual bool fullyIndependent( void ) const = 0;
	
	virtual Message* duplicate( Message& msg ) const = 0;

	virtual Message* replace( Message* oldMsg, Message& newMsg ) const = 0;
	
	virtual void free( Message* oldMsg ) const = 0;
	
	static inline boost::tribool isValid( const Message& msg );
	
	virtual boost::tribool doesConsume( const Message& msg, const Message& rhs ) const = 0;
	
	virtual void consume( Message& msg, Message& rhs ) const = 0;

	virtual size_t getThreadedThreshold( Message& msg ) const = 0;
	
	virtual boost::tribool doesBlockOnDispatch( Message& msg ) const = 0;
	
	virtual boost::tribool beginInvocations( Message& msg, size_t count ) const = 0;
	
	virtual void invoke( Message& msg, void* subscriber ) const = 0;

	virtual void endInvocations( Message& msg ) const = 0;

	virtual void execute( Message& msg ) const = 0;

	virtual void dropped( Message& msg, Message::EDropped reason ) const = 0;
	
private:
	virtual boost::tribool isValidSelf( const Message& msg ) const = 0;
};

template < typename MsgType, typename Allocator = NCAllocator< MsgType > >
class TMsgProxy : public MsgProxy
{
public:
	
	TMsgProxy( const IExceptionObserver::Ptr& excObserver = IExceptionObserver::Ptr(), const Allocator& alloc = Allocator() );
	
	virtual ~TMsgProxy( void );

	virtual size_t getMsgSize( void ) const;

	virtual bool fullyIndependent( void ) const;
	
	virtual Message* duplicate( Message& msg ) const;

	virtual Message* replace( Message* oldMsg, Message& newMsg ) const;
	
	virtual void free( Message* oldMsg ) const;
	
	virtual boost::tribool doesConsume( const Message& msg, const Message& rhs ) const;
	
	virtual void consume( Message& msg, Message& rhs ) const;

	virtual size_t getThreadedThreshold( Message& msg ) const;
	
	virtual boost::tribool doesBlockOnDispatch( Message& msg ) const;
	
	virtual boost::tribool beginInvocations( Message& msg, size_t count ) const;
	
	virtual void invoke( Message& msg, void* subscriber ) const;

	virtual void endInvocations( Message& msg ) const;

	virtual void execute( Message& msg ) const;

	virtual void dropped( Message& msg, Message::EDropped reason ) const;
	
private:
	virtual boost::tribool isValidSelf( const Message& msg ) const;
	
	IExceptionObserver::Ptr m_excObserver;
	mutable Allocator m_alloc;
};

}

}

#include "MsgProxy.inl"

#endif
